package org.qianye.soft.ext.toolbar;

import com.google.gwt.event.HandlerRegistration;
import com.sencha.gxt.data.shared.loader.*;

import org.qianye.soft.entity.Student;

import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/**
 * 分页组件
 *
 * @param <M>
 * @author 千叶
 */
public final class PagingToolbar<M> extends JPanel {

	private final JButton first, prev, next, last, refresh;

	private final JLabel beforePage, afterPage, displayText;
	private final LoaderHandler<PagingLoadConfig, ?> handler = new LoaderHandler<PagingLoadConfig, PagingLoadResult<?>>() {

		@Override
		public void onBeforeLoad(final BeforeLoadEvent<PagingLoadConfig> event) {
			loading = true;
			doEnableButtons(false);
		}

		@Override
		public void onLoad(LoadEvent<PagingLoadConfig, PagingLoadResult<?>> event) {
			doEnableButtons(true);
			PagingToolbar.this.onLoad(event);
		}

		@Override
		public void onLoadException(LoadExceptionEvent<PagingLoadConfig> event) {
			doEnableButtons(true);
			loading = false;
		}
	};
	protected PagingLoadConfig config;
	protected PagingLoader<PagingLoadConfig, ?> loader;
	private JTextField pageText;
	private boolean reuseConfig = true, loading;
	private int activePage = -1, pages, start, pageSize, totalLength;
	private HandlerRegistration handlerRegistration;

	/**
	 * 分页面板
	 *
	 * @param pageSize
	 */
	public PagingToolbar(int pageSize) {
		this.pageSize = pageSize;

		first = new JButton();
		first.setToolTipText("首页");
		first.setIcon(getIcon("page-first.gif"));
		first.addActionListener((ActionEvent evt) -> first());

		prev = new JButton();
		prev.setToolTipText("上一页");
		prev.setIcon(getIcon("page-prev.gif"));
		prev.addActionListener((ActionEvent evt) -> previous());

		next = new JButton();
		next.setToolTipText("下一页");
		next.setIcon(getIcon("page-next.gif"));
		next.addActionListener((ActionEvent evt) -> next());

		last = new JButton();
		last.setToolTipText("尾页");
		last.setIcon(getIcon("page-last.gif"));
		last.addActionListener((ActionEvent evt) -> last());

		refresh = new JButton();
		refresh.setToolTipText("刷新");
		refresh.setIcon(getIcon("page-refresh.gif"));
		refresh.addActionListener((ActionEvent e) -> refresh());

		beforePage = new JLabel("页");
		afterPage = new JLabel();
		displayText = new JLabel();

		pageText = new JTextField();
		pageText.setColumns(3);
		pageText.setToolTipText("请您输入页数");
		pageText.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
		pageText.addKeyListener(new KeyAdapter() {

			@Override
			public void keyTyped(KeyEvent e) {
				if ((!Character.isDigit(e.getKeyChar())) || (pageText.getText().length() + 1 > 4)) {
					e.setKeyChar('\f');
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					onPageChange();
				}
			}
		});

		Dimension size = new Dimension(30, 20);
		first.setPreferredSize(size);
		prev.setPreferredSize(size);
		next.setPreferredSize(size);
		last.setPreferredSize(size);
		refresh.setPreferredSize(size);

		setLayout(new BorderLayout());

		JPanel buttonPanel = new JPanel();
		buttonPanel.add(first);
		buttonPanel.add(prev);
		buttonPanel.add(new JLabel(getIcon("split.gif")));

		buttonPanel.add(beforePage);
		buttonPanel.add(pageText);
		buttonPanel.add(afterPage);

		buttonPanel.add(new JLabel(getIcon("split.gif")));
		buttonPanel.add(next);
		buttonPanel.add(last);

		buttonPanel.add(new JLabel(getIcon("split.gif")));
		buttonPanel.add(refresh);

		JPanel labPanel = new JPanel(new BorderLayout());
		labPanel.add(displayText, BorderLayout.CENTER);

		add(labPanel, BorderLayout.EAST);
		add(buttonPanel, BorderLayout.WEST);

	}

	protected void onLoad(LoadEvent<PagingLoadConfig, PagingLoadResult<?>> event) {
		loading = false;
		config = event.getLoadConfig();

		PagingLoadResult<?> result = event.getLoadResult();
		start = result.getOffset();
		totalLength = result.getTotalLength();
		activePage = (int) Math.ceil((double) (start + pageSize) / pageSize);
		pages = totalLength < pageSize ? 1 : (int) Math.ceil((double) totalLength / pageSize);

		if (activePage > pages && totalLength > 0) {
			last();
			return;
		} else if (activePage > pages) {
			start = 0;
			activePage = 1;
		}

		pageText.setText(String.valueOf((int) activePage));
		afterPage.setText("页共 " + pages + " 页");

		first.setEnabled(activePage != 1);
		prev.setEnabled(activePage != 1);
		next.setEnabled(activePage != pages);
		last.setEnabled(activePage != pages);

		int temp = activePage == pages ? totalLength : start + pageSize;
		String msg = "显示 " + (start + 1) + " - " + temp + "，共 " + totalLength + " 条";
		if (totalLength == 0) {
			msg = "没有数据需要显示";
		}
		displayText.setText(msg);
	}

	protected void onPageChange() {
		String value = pageText.getText();
		if (value.equals("")) {
			pageText.setText(String.valueOf((int) activePage));
			return;
		}
		int p = Integer.parseInt(value);
		setActivePage(p);
	}

	public void setActivePage(int page) {
		if (page > pages) {
			last();
			return;
		}
		if (page != activePage && page > 0 && page <= pages) {
			doLoadRequest(--page * pageSize, pageSize);
		} else {
			pageText.setText(String.valueOf((int) activePage));
		}
	}

	protected void doLoadRequest(int offset, int limit) {
		if (reuseConfig && config != null) {
			config.setOffset(offset);
			config.setLimit(pageSize);

		} else {
			loader.setLimit(pageSize);
			loader.load(offset, limit);
		}

		new Thread() {
			public void run() {
				loader.load(config);
			}
		}.start();
	}

	public void refresh() {
		if (!loading) {
			doLoadRequest(start, pageSize);
		}
	}

	public void first() {
		if (!loading) {
			doLoadRequest(0, pageSize);
		}
	}

	public void previous() {
		if (!loading) {
			doLoadRequest(Math.max(0, start - pageSize), pageSize);
		}
	}

	public void next() {
		if (!loading) {
			doLoadRequest(start + pageSize, pageSize);
		}
	}

	public void last() {
		if (!loading) {
			if (totalLength > 0) {
				int extra = totalLength % pageSize;
				int lastStart = extra > 0 ? (totalLength - extra) : totalLength - pageSize;
				doLoadRequest(lastStart, pageSize);
			}
		}
	}

	/**
	 * @return
	 */
	private ImageIcon getIcon(String filename) {
		return new ImageIcon(PagingToolbar.class.getResource("images/" + filename));
	}

	public void bind(PagingLoader<PagingLoadConfig, PagingLoadResult<Student>> loader) {
		if (this.loader != null) {
			handlerRegistration.removeHandler();
		}
		this.loader = (PagingLoader) loader;
		if (loader != null) {
			loader.setLimit(pageSize);
			handlerRegistration = loader.addLoaderHandler((LoaderHandler) handler);
		}
	}

	protected void doEnableButtons(boolean enabled) {
		first.setEnabled(enabled);
		prev.setEnabled(enabled);
		beforePage.setEnabled(enabled);
		pageText.setEnabled(enabled);
		afterPage.setEnabled(enabled);
		next.setEnabled(enabled);
		last.setEnabled(enabled);
		displayText.setEnabled(enabled);
		refresh.setEnabled(enabled);
	}
}
